import React, { useState, useRef, useEffect } from 'react';
import { Form, Input, Icon } from 'antd';
import { useAntdTable, useUpdateEffect } from '@umijs/hooks';
import PropTypes from 'prop-types';
import Trigger from 'rc-trigger';
import 'rc-trigger/assets/index.css';
import isFunction from 'lodash/isFunction';
import SlickTable from '@/components/SlickTable';
import request from '@/utils/request';
import styles from './index.less';

function getTableData({ current, pageSize, method, url, ...rest }) {
  return request(url, {
    method,
    data: {
      page: current,
      pageNum: current,
      pageSize,
      rowNum: pageSize,
      sortName: '',
      sortOrder: 'asc',
      ...rest,
    },
  }).then(res => {
    if (res.success) {
      if (Array.isArray(res.data.records)) {
        return {
          total: res.data.total,
          data: res.data.records.map(val => {
            const { children, ...rest } = val;
            return rest;
          }),
        };
      }
    }
    return {
      total: 0,
      data: [],
    };
  });
}

function getValue(value, tokenSeparators, label) {
  const result = [];
  if (Array.isArray(value)) {
    value.map(val => {
      return result.push(val[label]);
    });
  } else if (typeof value === 'string') {
    result.push(value);
  }
  return result.join(tokenSeparators);
}

function ComboGrid({
  form,
  onChange,
  value,
  url,
  method,
  action,
  placeholder,
  searchPlaceholder,
  columns,
  rowKey,
  label,
  tokenSeparators,
  extra,
  pick,
  disabled,
  params,
  onConfirm,
  ...restProps
}) {
  const [selectedRows, setSelectedRows] = useState(value);
  const [keyword, setKeyword] = useState('');
  const [open, setOpen] = useState(false);
  const tableEl = useRef(null);
  // tableProps格式{dataSource,loading,onChange,pagination:{current,pageSize,total}}
  const { tableProps } = useAntdTable(
    query => {
      /**
       * query包含 分页和表单值，格式如下：
       * {current: 1,filters: {},pageSize: 2,sorter:{},bulletinTitle:''}
       * expand=true 表示高级搜索；高级搜索无视快捷搜索上的bulletinTitle值；反之一样
       */
      let filterVal = {};
      if (keyword) {
        filterVal = { filterVal: keyword };
      }
      return getTableData({ ...query, pageSize: 5, method, url, ...filterVal, ...params });
    },
    [keyword, JSON.stringify(params), url],
    {
      defaultPageSize: 5,
    }
  );
  const { pagination, ...restTableProps } = tableProps;

  function onPopupVisibleChange(isVisible) {
    if (!isVisible) {
      onConfirm(selectedRows);
    }
    if (isVisible) {
      setKeyword('');
    }
    setOpen(isVisible);
  }

  /**
   * 1、input元素被get包裹 会从props带入onChange方法,selectedRows 保证form取到的值是实时最新的
   * 2、只在更新阶段执行onChange，避免在初始化时触发rule校验（如果被getFieldDecorator包裹）
   */
  useUpdateEffect(() => {
    if (isFunction(onChange)) {
      onChange(selectedRows);
    }
  }, [selectedRows, onChange]);

  /**
   * 外部通过setFieldsValue设置值的时候，即时更新
   */
  useEffect(() => {
    if (Array.isArray(value)) {
      setSelectedRows(value);
    }
  }, [value]);

  return (
    <Trigger
      className={styles.combogrid}
      action={[action]}
      popupAlign={{
        overflow: {
          adjustX: true, // true 表示当下拉框宽度>所在容器宽度时 会自动切换 左右对齐
          adjustY: true, // true 表示当下拉框高度 > 所在容器高度是 会自动切换 上下对齐
        },
        offset: [0, 4],
      }}
      getPopupContainer={trigger => trigger.parentNode}
      onPopupVisibleChange={isVisible => onPopupVisibleChange(isVisible)}
      mouseEnterDelay={0.3}
      builtinPlacements={{
        left: {
          points: ['cr', 'cl'],
        },
        right: {
          points: ['cl', 'cr'],
        },
        top: {
          points: ['bc', 'tc'],
        },
        bottom: {
          points: ['tc', 'bc'],
        },
        topLeft: {
          points: ['bl', 'tl'],
        },
        topRight: {
          points: ['br', 'tr'],
        },
        bottomRight: {
          points: ['tr', 'br'],
        },
        bottomLeft: {
          points: ['tl', 'bl'],
        },
      }}
      popupClassName={styles.combogridDropdown}
      popupVisible={open}
      popup={
        <div>
          <Input.Search
            placeholder={searchPlaceholder}
            allowClear
            className={styles.search}
            onSearch={val => setKeyword(val)}
          />
          <SlickTable
            ref={tableEl}
            extra={extra}
            rowKey={rowKey}
            pick={pick}
            data={{ pagination }}
            {...restTableProps}
            selectedRowKeys={selectedRows.map(row => row[rowKey])}
            onSelectRow={selectedRows => {
              const result = [];
              selectedRows.map(val => result.push(val.orgName));
              setSelectedRows(selectedRows);
              if (pick === 'radio') {
                // setOpen(false);
                setTimeout(() => {
                  setOpen(false);
                }, 250);
              }
            }}
            columns={columns}
            selectedRows={selectedRows}
          />
        </div>
      }
      {...restProps}
    >
      <Input
        placeholder={placeholder}
        disabled={disabled}
        // allowClear
        // onChange={e => {
        //   window.tableEl = tableEl;
        //   if (tableEl && tableEl.current) {
        //     tableEl.current.cleanSelectedKeys([], []);
        //   }
        // }}
        suffix={<Icon type="table" />}
        value={getValue(selectedRows, tokenSeparators, label)}
      />
    </Trigger>
  );
}

ComboGrid.defaultProps = {
  value: [],
  method: 'post',
  placeholder: '',
  searchPlaceholder: '',
  action: 'click',
  stretch: 'width',
  popupStyle: {},
  popupPlacement: 'bottomLeft',
  tokenSeparators: ',',
  destroyPopupOnHide: false,
  disabled: false,
  extra: null,
  pick: 'checkbox',
  params: {},
  onConfirm: () => {},
};

ComboGrid.propTypes = {
  value: PropTypes.array,
  method: PropTypes.oneOf(['post', 'get']),
  url: PropTypes.string.isRequired,
  label: PropTypes.string.isRequired,
  rowKey: PropTypes.oneOfType([PropTypes.string, PropTypes.func]).isRequired,
  columns: PropTypes.arrayOf(PropTypes.object).isRequired,
  placeholder: PropTypes.string,
  searchPlaceholder: PropTypes.string,
  tokenSeparators: PropTypes.string,
  action: PropTypes.oneOf(['hover', 'click']),
  popupStyle: PropTypes.object,
  stretch: PropTypes.oneOf(['width', 'height', 'minWidth', 'minHeight']),
  popupPlacement: PropTypes.oneOf([
    'top',
    'right',
    'bottom',
    'right',
    'topLeft',
    'topRight',
    'bottomLeft',
    'bottomRight',
  ]),
  destroyPopupOnHide: PropTypes.bool,
  disabled: PropTypes.bool,
  params: PropTypes.object,
  extra: PropTypes.oneOfType([PropTypes.func, PropTypes.element]),
  pick: PropTypes.oneOf(['checkbox', 'radio']),
  onConfirm: PropTypes.func,
};

export default Form.create()(ComboGrid);
